package com.ruicar.afs.cloud.afscase.processor.notice;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruicar.afs.cloud.afscase.approvetask.entity.WorkProcessScheduleInfo;
import com.ruicar.afs.cloud.afscase.approvetask.entity.WorkProcessScheduleInfoTemp;
import com.ruicar.afs.cloud.afscase.approvetask.entity.WorkTaskPool;
import com.ruicar.afs.cloud.afscase.approvetask.service.CaseApproveRecordService;
import com.ruicar.afs.cloud.afscase.approvetask.service.WorkProcessScheduleInfoService;
import com.ruicar.afs.cloud.afscase.approvetask.service.WorkProcessScheduleInfoTempService;
import com.ruicar.afs.cloud.afscase.approvetask.service.WorkTaskPoolService;
import com.ruicar.afs.cloud.afscase.infomanagement.entity.CaseBaseInfo;
import com.ruicar.afs.cloud.afscase.infomanagement.entity.CaseChannelInfo;
import com.ruicar.afs.cloud.afscase.infomanagement.entity.CaseCustInfo;
import com.ruicar.afs.cloud.afscase.infomanagement.service.CaseBaseInfoService;
import com.ruicar.afs.cloud.afscase.infomanagement.service.CaseChannelInfoService;
import com.ruicar.afs.cloud.afscase.infomanagement.service.CaseCustInfoService;
import com.ruicar.afs.cloud.afscase.processor.enums.WorkflowType;
import com.ruicar.afs.cloud.afscase.processor.util.WorkflowTypeUtil;
import com.ruicar.afs.cloud.afscase.processor.vo.NormalLineConfigDataVO;
import com.ruicar.afs.cloud.afscase.risk.service.CaseTortoiseService;
import com.ruicar.afs.cloud.common.core.constant.CommonConstants;
import com.ruicar.afs.cloud.common.core.enums.AfsEnumUtil;
import com.ruicar.afs.cloud.common.core.feign.api.RemoteUserService;
import com.ruicar.afs.cloud.common.core.security.dto.UserInfo;
import com.ruicar.afs.cloud.common.core.util.IResponse;
import com.ruicar.afs.cloud.common.modules.afscorebusiness.enums.*;
import com.ruicar.afs.cloud.seats.entity.UserCollocation;
import com.ruicar.afs.cloud.seats.service.UserCollocationService;
import com.ruicar.afs.cloud.workflow.api.dto.afsprocess.request.FlowExceptionRequest;
import com.ruicar.afs.cloud.workflow.api.dto.afsprocess.request.TaskAssignRequest;
import com.ruicar.afs.cloud.workflow.api.dto.afsprocess.request.TaskCreateRequest;
import com.ruicar.afs.cloud.workflow.api.dto.afsprocess.request.UpdateBizDataRequest;
import com.ruicar.afs.cloud.workflow.api.dto.afsprocess.response.FlowExceptionResponse;
import com.ruicar.afs.cloud.workflow.api.dto.afsprocess.response.TaskAssignResponse;
import com.ruicar.afs.cloud.workflow.api.dto.afsprocess.response.TaskCreateResponse;
import com.ruicar.afs.cloud.workflow.api.dto.afsprocess.response.UpdateBizDataResponse;
import com.ruicar.afs.cloud.workflow.gwt.processor.AfsWorkFlowNoticeProcessor;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * @Description 信审常规流程通知处理
 * @Author Peng_Jinbo
 * @Date 2020/07/15 11:03
 */
@Component
@AllArgsConstructor
@Slf4j
public class NormalNoticeProcessor implements AfsWorkFlowNoticeProcessor {

    WorkTaskPoolService workTaskPoolService;
    WorkProcessScheduleInfoService workProcessScheduleInfoService;
    WorkProcessScheduleInfoTempService workProcessScheduleInfoTempService;
    CaseChannelInfoService caseChannelInfoService;
    CaseCustInfoService caseCustInfoService;
    UserCollocationService userCollocationService;
    RemoteUserService remoteUserService;
    CaseBaseInfoService caseBaseInfoService;
    CaseTortoiseService caseTortoiseService;
    CaseApproveRecordService caseApproveRecordService;

    @Override
    public List<String> afsFLowKeys() {
        return Arrays.asList(new String[]{
                WorkflowType.NORMAL_NEW.getAfsFlowKey(),
                WorkflowType.NORMAL_OLD.getAfsFlowKey(),
                WorkflowType.NORMAL_APPOINT.getAfsFlowKey(),
                WorkflowType.CHANGE_ASSETS.getAfsFlowKey(),
                WorkflowType.RECONSIDER_APPLY.getAfsFlowKey(),
                WorkflowType.FORMAL_REVIEW.getAfsFlowKey()
        });
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public TaskCreateResponse taskCreated(TaskCreateRequest taskCreateRequest) {
        log.info("流程节点创建，更新流程实例信息：taskCreated ==>{}", taskCreateRequest);
        WorkProcessScheduleInfo info = workProcessScheduleInfoService.getById(Convert.toLong(taskCreateRequest.getBizDataId()));
        if (Objects.isNull(info)) {
            WorkProcessScheduleInfoTemp temp = workProcessScheduleInfoTempService.getById(Convert.toLong(taskCreateRequest.getBizDataId()));
            info = new WorkProcessScheduleInfo();
            BeanUtil.copyProperties(temp, info, new String[]{"createBy", "createTime"});
            workProcessScheduleInfoService.save(info);
        }
        log.info("节点配置信息 ==> {}", taskCreateRequest.getTaskMemo());
        if (JSON.isValid(taskCreateRequest.getTaskMemo())) {
            NormalLineConfigDataVO normalConfigData = JSONObject.parseObject(taskCreateRequest.getTaskMemo(), NormalLineConfigDataVO.class);
            info.setFirstTrail(Convert.toStr(normalConfigData.getFirstTrail(), WhetherEnum.NO.getCode()));
            info.setLastTrail(Convert.toStr(normalConfigData.getLastTrail(), WhetherEnum.NO.getCode()));
            info.setUncertainNode(Convert.toStr(normalConfigData.getUncertain(), WhetherEnum.NO.getCode()));
        } else {
            info.setLastTrail(WhetherEnum.NO.getCode());
            info.setFirstTrail(WhetherEnum.NO.getCode());
            info.setUncertainNode(WhetherEnum.NO.getCode());
        }
        info.setCurrentNodeId(taskCreateRequest.getNodeId());
        info.setCurrentNodeName(taskCreateRequest.getTaskName());
        if (StrUtil.isBlank(info.getStageId())) {
            info.setAfsFlowKey(taskCreateRequest.getAfsFlowKey());
            info.setStageId(taskCreateRequest.getFlowInstanceId());
            info.setStageNo(taskCreateRequest.getServiceId());
        }
        workProcessScheduleInfoService.updateById(info);
        TaskCreateResponse response = new TaskCreateResponse();
        response.setSuccess(true);
        return response;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public TaskAssignResponse taskAssigned(TaskAssignRequest taskAssignRequest) {
        log.info("任务处理人实例获取，创建待办任务:taskAssigned ==>{}", taskAssignRequest);
        WorkProcessScheduleInfo workflowInstance = workProcessScheduleInfoService.getById(taskAssignRequest.getBizDataId());

        CaseChannelInfo channelInfo = caseChannelInfoService.getOne(
                Wrappers.<CaseChannelInfo>lambdaQuery().eq(CaseChannelInfo::getApplyNo, workflowInstance.getApplyNo())
        );
        CaseCustInfo custInfo = caseCustInfoService.getOne(
                Wrappers.<CaseCustInfo>lambdaQuery().eq(CaseCustInfo::getApplyNo, workflowInstance.getApplyNo())
                        .eq(CaseCustInfo::getCustRole, CustRoleEnum.MIANCUST.getCode())
        );
        UserCollocation userCollocation = userCollocationService.getOne(
                Wrappers.<UserCollocation>lambdaQuery().eq(UserCollocation::getLoginName, taskAssignRequest.getUserName())
        );
        WorkTaskPool taskPool = new WorkTaskPool();
        taskPool.setStageId(Convert.toStr(workflowInstance.getId()));
        taskPool.setStageNo(workflowInstance.getStageNo());
        taskPool.setTaskNodeId(taskAssignRequest.getTaskNodeId());
        taskPool.setTaskNodeName(taskAssignRequest.getTaskName());
        taskPool.setApplyNo(workflowInstance.getApplyNo());
        taskPool.setDealerName(Objects.nonNull(channelInfo) ? channelInfo.getDealerName() : "");
        taskPool.setCustName(custInfo.getCustName());
        taskPool.setApproveStaff(taskAssignRequest.getUserName());
        // 可能处理人为经销商
        if (Objects.nonNull(channelInfo) && StrUtil.equals(taskAssignRequest.getUserName(), Convert.toStr(channelInfo.getId()))) {
            taskPool.setApproveStaffName(channelInfo.getSaleAdvisor());
        } else {
            taskPool.setApproveStaffName(getTaskHandlerUserName(taskAssignRequest));
        }
        taskPool.setStartTime(new Date());
        taskPool.setIsOpen(WhetherEnum.NO.getCode());
        taskPool.setStartTime(new Date());
        taskPool.setProcessType(WorkflowTypeUtil.getApproveTypeCode(workflowInstance.getAfsFlowKey()));
        taskPool.setWorkflowDisposeId(taskAssignRequest.getId());
        if (Objects.nonNull(userCollocation)) {
            taskPool.setApproveLeader(userCollocation.getGroupLeaderLoginName());
            taskPool.setApproveLeaderName(userCollocation.getGroupLeader());
        }
        //add by yk.Li 2020/7/20
        taskPool.setContractNo(workflowInstance.getContractNo());
        // 是否首尾节点
        taskPool.setFirstNode(workflowInstance.getFirstTrail());
        taskPool.setLastNode(workflowInstance.getLastTrail());
        if(StrUtil.equals(workflowInstance.getUncertainNode(),WhetherEnum.YES.getCode())) {
            taskPool.setLastNode(WhetherEnum.NO.getCode());
        }
        workTaskPoolService.save(taskPool);
        arrivalRecord(taskPool,workflowInstance);
        changeCaseStatusWhenCreatFirstTask(workflowInstance);
        TaskAssignResponse response = new TaskAssignResponse();
        response.setSuccess(true);
        return response;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public UpdateBizDataResponse updateBizData(UpdateBizDataRequest updateBizDataRequest) {
        log.info("线上数据回写:updateBizData ==>{}", updateBizDataRequest);
        if (StrUtil.isNotBlank(updateBizDataRequest.getConfigData())) {
        }
        UpdateBizDataResponse response = new UpdateBizDataResponse();
        response.setSuccess(true);
        return response;
    }

    @Override
    public FlowExceptionResponse assignError(FlowExceptionRequest flowExceptionRequest){
        LOGGER.info("接收到[任务分配]流程异常通知:{}", JSON.toJSONString(flowExceptionRequest));
        processFlowException(flowExceptionRequest,FlowParseEnum.ASSIGN);
        FlowExceptionResponse response = new FlowExceptionResponse();
        response.setSuccess(true);
        return response;
    }

    @Override
    public FlowExceptionResponse dataGetError(FlowExceptionRequest flowExceptionRequest){
        LOGGER.info("接收到[数据获取]流程异常通知:{}", JSON.toJSONString(flowExceptionRequest));
        processFlowException(flowExceptionRequest,FlowParseEnum.DATA);
        FlowExceptionResponse response = new FlowExceptionResponse();
        response.setSuccess(true);
        return response;
    }

    @Override
    public FlowExceptionResponse defaultError(FlowExceptionRequest flowExceptionRequest){
        LOGGER.info("接收到[默认(未定义)]流程异常通知:{}", JSON.toJSONString(flowExceptionRequest));
        processFlowException(flowExceptionRequest,FlowParseEnum.DEFAULT);
        FlowExceptionResponse response = new FlowExceptionResponse();
        response.setSuccess(true);
        return response;
    }

    /**
    * @Description 保存流程异常信息
    * @Author Peng_Jinbo
    * @Date 2020/8/7 15:17
    */
    @Transactional
    public void processFlowException(FlowExceptionRequest flowExceptionRequest, FlowParseEnum flowParseEnum){

        WorkProcessScheduleInfo info = workProcessScheduleInfoService.getById(flowExceptionRequest.getBizDataId());
        String flowTypeName = WorkflowTypeUtil.getApproveTypeCode(info.getAfsFlowKey());
        // 常规审批流程处理
        if(Objects.nonNull(info)
                && StrUtil.equals(flowTypeName, ProcessTypeEnum.GENERA_APPROVE.getCode())){
            CaseBaseInfo baseInfo = caseBaseInfoService.getOne(
                    Wrappers.<CaseBaseInfo>lambdaQuery()
                            .eq(CaseBaseInfo::getApplyNo,info.getApplyNo())
            );
            if(flowParseEnum == FlowParseEnum.ASSIGN) {
                baseInfo.setBusinessStateIn(AfsEnumUtil.key(BusinessStateInEnum.TASK_ASSIGN));
            }
            baseInfo.setFlowParseFlag(WhetherEnum.YES.getCode());
            baseInfo.setFlowParseType(AfsEnumUtil.key(flowParseEnum));
            baseInfo.setFlowParseId(info.getId().toString());
            baseInfo.setFlowParseExceptionId(flowExceptionRequest.getExceptionId());
            caseBaseInfoService.updateById(baseInfo);
            log.info("流程异常接收完毕 => FlowExceptionId "  + flowExceptionRequest.getExceptionId());
        }

    }

    /**
    * @Description 常规审批创建首个任务时将案件状态从分配中改为待审核
    * @Author Peng_Jinbo
    * @Date 2020/8/7 18:09
    */
    private void changeCaseStatusWhenCreatFirstTask(WorkProcessScheduleInfo workflowInstance) {
        String flowTypeName = WorkflowTypeUtil.getApproveTypeCode(workflowInstance.getAfsFlowKey());
        if (Objects.nonNull(workflowInstance)
                && (StrUtil.equals(flowTypeName, ProcessTypeEnum.GENERA_APPROVE.getCode())
                    || StrUtil.equals(flowTypeName, ProcessTypeEnum.FORMAL_REVIEW.getCode()))) {

            List<String> businessStatusInList = new ArrayList<>();
            businessStatusInList.add(AfsEnumUtil.key(BusinessStateInEnum.TASK_ASSIGN));
            businessStatusInList.add(AfsEnumUtil.key(BusinessStateInEnum.TASK_ASSIGNING));
            if (StrUtil.equals(workflowInstance.getFirstTrail(),WhetherEnum.YES.getCode())) {
                caseBaseInfoService.update(
                        Wrappers.<CaseBaseInfo>lambdaUpdate()
                                .eq(CaseBaseInfo::getApplyNo, workflowInstance.getApplyNo())
                                .in(CaseBaseInfo::getBusinessStateIn, businessStatusInList)
                                .set(CaseBaseInfo::getBusinessStateIn, AfsEnumUtil.key(BusinessStateInEnum.WAIT_CHECK))
                                .set(CaseBaseInfo::getFlowParseFlag, WhetherEnum.NO.getCode())
                                .set(CaseBaseInfo::getFlowParseExceptionId, "")
                                .set(CaseBaseInfo::getFlowParseType, "")
                                .set(CaseBaseInfo::getFlowParseId, "")
                );
            }
        }
    }



    /**
     * @Description 获取处理人名称
     * @Author Peng_Jinbo
     * @Date 2020/7/17 14:24
     */
    public String getTaskHandlerUserName(TaskAssignRequest taskAssignRequest) {
        String userName = taskAssignRequest.getUserName();
        IResponse<UserInfo> response = remoteUserService.info(taskAssignRequest.getUserName());
        if (CommonConstants.SUCCESS.equals(response.getCode()) && Objects.nonNull(response.getData())) {
            userName = response.getData().getSysUser().getUserRealName();
        }
        return userName;
    }


    /**
     * @Description 记录任务抵达时间
     * @Author Peng_Jinbo
     * @Date 2020/9/11 17:30
     */
    private void arrivalRecord(WorkTaskPool taskPool,WorkProcessScheduleInfo info) {
        WorkflowTypeEnum flowType = WorkflowTypeUtil.getType(info.getAfsFlowKey()).getApproveType();
        if(ProcessTypeEnum.GENERA_APPROVE == flowType
                ||ProcessTypeEnum.CHANGE_ASSETS == flowType
                ||ProcessTypeEnum.RECONSIDER_APPLY == flowType
                ||ProcessTypeEnum.FORMAL_REVIEW == flowType){
            caseApproveRecordService.taskArrival(taskPool);
        }
    }
}
